package com.pactera.miyuangroup.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.pactera.miyuangroup.util.JwtUtils;
import com.pactera.miyuangroup.vo.request.web.LoginPara;
import com.pactera.miyuangroup.vo.response.AccessToken;
import com.pactera.miyuangroup.vo.response.ResultModel;
import com.pactera.miyuangroup.vo.response.ResultStatusCode;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Base64;
import java.util.Date;

import static java.util.Collections.emptyList;

/**
 * jwt登录拦截
 *
 * @author Wangwu
 * @create 2018-03-30 下午2:13
 **/
@Slf4j
public class JwtLoginFilter extends UsernamePasswordAuthenticationFilter {

    private AuthenticationManager authenticationManager;

    public JwtLoginFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }


    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
        ResultModel r = ResultModel.fail(ResultStatusCode.UNKNOWN_ERROR);
        try {
            LoginPara login = JSON.parseObject(request.getInputStream(), LoginPara.class, Feature.AutoCloseSource);
            return authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            login.getUserName(),
                            login.getPassword(),
                            emptyList())
            );
        } catch (UsernameNotFoundException e) {
            //用户找不到
            r = ResultModel.fail(ResultStatusCode.INVALID_PASSWORD);
        } catch (BadCredentialsException e) {
            //坏的凭据
            r = ResultModel.fail(ResultStatusCode.INVALID_TOKEN);
        } catch (AccountExpiredException e) {
            //账户过期
            r = ResultModel.fail(ResultStatusCode.ACCOUNT_NOT_AVAILABLE);
        } catch (LockedException e) {
            //账户锁定
            r = ResultModel.fail(ResultStatusCode.ACCOUNT_NOT_AVAILABLE);
        } catch (DisabledException e) {
            //账户不可用
            r = ResultModel.fail(ResultStatusCode.ACCOUNT_NOT_AVAILABLE);
        } catch (CredentialsExpiredException e) {
            //证书过期
            r = ResultModel.fail(ResultStatusCode.INVALID_TOKEN);
        } catch (Exception e) {
            //未知错误
            log.error("未知错误：{}", e.getMessage());
        }
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        try {
            response.getWriter().write(JSON.toJSONString(r));
            response.getWriter().close();
        } catch (IOException e) {
            log.error("response write 错误：{}", e.getMessage());
        }
        return null;
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                                            FilterChain chain, Authentication authResult) throws IOException, ServletException {
        String token = Jwts.builder()
                .setSubject(((User) authResult.getPrincipal()).getUsername())
                .setExpiration(new Date(System.currentTimeMillis() + JwtUtils.getAuthorizationTTLMillis()))
                .signWith(SignatureAlgorithm.HS512, JwtUtils.getAuthorizationPrivateSecret())
                .compact();
        token = Base64.getEncoder().encodeToString(JwtUtils.getTokenHeader(token).getBytes("utf-8"));
        //response.addHeader("Authorization", token);
        AccessToken accessToken = new AccessToken();
        accessToken.setAccess_token(token);
        accessToken.setExpires_in(JwtUtils.getAuthorizationTTLMillis());
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        response.getWriter().write(JSON.toJSONString(ResultModel.ok(accessToken)));
        response.getWriter().close();

    }
}
